package com.boat.framework.common.util;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * json工具，基于jackson。用于包装各种场景的ObjectMapper，并基于此进行对象序列化操作
 * 
 * @author 周江
 *
 */
@Slf4j
public class JsonUtils {
	private static ObjectMapper DEFAULT_MAPPER = new DefaultObjectMapper();

	private JsonUtils() {
		
	}
	/**
	 * 对象转换成 json 字符串。
	 */
	public static String toJson(Object obj) {
		return toJson(DEFAULT_MAPPER, obj);
	}

	/**
	 * 将json通过类型转换成普通javabean对象（pojo）
	 */
	@SuppressWarnings("unchecked")
	public static <T> T toBean(String json, Class<T> clazz) {
		if (StrUtil.isBlank(json)) {
			return null;
		}

		try {
			return clazz.equals(String.class) ? (T) json : DEFAULT_MAPPER.readValue(json, clazz);
		} catch (Exception ex) {
			log.warn("字符串" + json + "解析成对象" + clazz.getName() + "时异常", ex);
		}
		return null;
	}
	
	/**
	 * Json转换为list
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <T> List<T> toList(String json, Class<T> itemClazz) {
		if (StrUtil.isBlank(json)) {
			return new ArrayList(0);
		}
		List lstObjs = (List<?>) toBean(json, List.class);
		if(lstObjs == null) {
			return new ArrayList(0);
		}
		List lstResult = new ArrayList(lstObjs.size());

		for (Iterator objIter = lstObjs.iterator(); objIter.hasNext();) {
			Object objT = DEFAULT_MAPPER.convertValue(objIter.next(), itemClazz);
			lstResult.add(objT);
		}
		return lstResult;
	}
	
	/**
	 * Json转换为Map
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map<String, Object> toMap(String json) {
		if (StrUtil.isBlank(json)) {
			return new HashMap<>();
		}
		
		try {
			return (Map) DEFAULT_MAPPER.readValue(json, HashMap.class);
		} catch (Exception ex) {
			log.warn("Json to Map error", ex);
		}
		return null;
	}

	public static ObjectMapper getDefaultObjectMapper() {
		return DEFAULT_MAPPER;
	}

	private static String toJson(ObjectMapper om, Object obj) {
		if (obj == null) {
			return null;
		}

		try {
			return obj instanceof String ? (String) obj : om.writeValueAsString(obj);
		} catch (Exception e) {
			throw new RuntimeException("object(" + obj + ") to json exception.", e);
		}
	}

	// --------定义各种场景下的mapper
	// defaultMapper，用于http接口返回结果序列化
	private static class DefaultObjectMapper extends ObjectMapper {
		private DefaultObjectMapper() {
			super();
			// null和空值不序列化。如果只需要null不序列化, 改为NON_NULL
			setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
			// 不确定的属性项上不要失败, 默认如果失败会抛出 JsonMappingException
			configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
			// 日期不用 utc 方式显示(utc 是一个整数值)
			configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
			// 时间格式
			setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
			// 不确定值的枚举返回 null
			configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
		}
	}
}
